package com.hongdee.base.util;

import com.hongdee.base.entity.BaseEntity;
import com.hongdee.base.imp.entity.TExpDataVoEntity;
import com.hongdee.base.imp.vo.ExcelSchemePropertyVo;
import com.hongdee.base.imp.vo.ExcelSchemeVo;
import com.hongdee.common.util.DateUtils;
import com.hongdee.common.util.StringUtil;
import com.hongdee.poi.ConcurrentDateFormatUtil;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 名  称:EntityFactory
 * 类  型: class
 * 描  述: 用一句话描述类的作用
 * 路  径:com.hongdee.base.util
 * 作  者:My
 * 日  期:2017/2/16 10:49
 */
public final class EntityFactory {
    private static final DecimalFormat NUM_FORMATE = new DecimalFormat("#.##");

    private EntityFactory() {

    }

    public static BaseEntity BuildEntity(final ExcelSchemeVo excelScheme,
                                         final List<String> valueList, String uid, String companyId,TExpDataVoEntity expData) {
        ////非空有效性判断
        if (null == excelScheme
                || null == excelScheme.getProperyList()
                || excelScheme.getProperyList().size() == 0
                || null == valueList
                || valueList.isEmpty()) {
            return null;
        }

        if (StringUtils.isEmpty(excelScheme.getClsQualifiedName())) {
            return null;
        }

        ////关键信息列非空判断
//        if (valueList.size() < excelScheme.getKeyColumn() || StringUtils.isEmpty(valueList.get(excelScheme.getKeyColumn() - 1)))
//            return null;

        try {
            Class cls = Class.forName(excelScheme.getClsQualifiedName());
            if (null == cls) {
                return null;
            }

            BaseEntity be = null;
            be = (BaseEntity) cls.newInstance();
            Field f = null;
            String typeName = null;
            String value = null;

            ExcelSchemePropertyVo espVo;

            Boolean checkFlag=true;
            StringBuffer errorStr=new StringBuffer();
            List<String> headList=new ArrayList<>();
            List<Object> rowList=new ArrayList<>();
            for (int i = 0; i < excelScheme.getProperyList().size(); i++) {

                ////列索引要大于0
                if (excelScheme.getProperyList().get(i).getColumnNum() < 1) {
                    continue;
                }
                ////列索引大于当前数据数量
                if (excelScheme.getProperyList().get(i).getColumnNum() > valueList.size()) {
                    continue;
                }
                espVo = excelScheme.getProperyList().get(i);
                headList.add(espVo.getPropertyTitle());//将标题加入到headList中
                //存的是个空的，
                value = valueList.get(excelScheme.getProperyList().get(i).getColumnNum() - 1);
                rowList.add(value);
                //如果是行合并单元格
                if ("true".equals(espVo.getIsMerge())) {
                    //上一行值为空，且当前值不为空，将当前行的值赋值，以便下一行取用
                    if (espVo.getPreRowValue() == null || espVo.getPreRowValue().length() == 0) {
                        if (value != null && value.length() > 0) {
                            espVo.setPreRowValue(value);
                        }
                    } else {
                        //当前行为空时，取上一行的值
                        if ((value == null || value.length() == 0)) {
                            value = espVo.getPreRowValue();
                        } else {
                            if (!value.equals(espVo.getPreRowValue())) {
                                espVo.setPreRowValue(value);
                            }
                        }
                    }

                }
                f = cls.getDeclaredField(excelScheme.getProperyList().get(i).getPropertyName());
                f.setAccessible(true);
                typeName = f.getType().getTypeName();
                //空值判断
                if (value != null && value.length() > 0) {
                    if (typeName.endsWith("String")) {
                        f.set(be, value);
                    } else if (typeName.endsWith("Integer") || typeName.endsWith("int")) {
                        f.setInt(be, Integer.valueOf(value));
                    } else if (typeName.endsWith("BigDecimal")) {
                        f.set(be, new BigDecimal(value));
                    } else if (typeName.endsWith("Double") || typeName.endsWith("double")) {
                        f.setDouble(be, Double.valueOf(value));
                    } else if (typeName.endsWith("Float") || typeName.endsWith("float")) {
                        f.setFloat(be, Float.valueOf("0" + value));
                    } else if (typeName.endsWith("Long") || typeName.endsWith("long")) {
                        f.set(be, Long.valueOf(value));
                    } else if (typeName.endsWith("Date") && !StringUtils.isEmpty(value)) {
                        f.set(be, ConcurrentDateFormatUtil.parse(value));
                    }
                }
                checkFlag=checkImpValue(value,checkFlag,espVo,errorStr);
            }
            ///设置基本信息：创建人，创建时间等
            be.setCreateTime(System.currentTimeMillis());
            be.setCreateUser(uid);
            be.setUpdateTime(System.currentTimeMillis());
            be.setUpdateUser(uid);
            //设置导入公司
            f = cls.getDeclaredField("companyId");
            if (null != f) {
                f.setAccessible(true);
                f.set(be, companyId);
            }
            ///设置基本信息：创建人，创建时间等
//
//            ////设置上传特定属性
//            f = cls.getDeclaredField("uploadKey");
//            if (null != f) {
//                f.setAccessible(true);
//                f.set(be, excelScheme.getUploadKey());
//            }
            if(!checkFlag){//检测值是false 说明没通过检测 设置返回值为空
                if(expData!=null) {
                    headList.add("错误提示");
                    expData.setHeadList(headList);
                    rowList.add(errorStr.toString());
                    expData.setBodyList(rowList);
                }
                //将本条数据 放置在错误数据集合里
                return null;
            }else {
                return be;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }


    }


    private static boolean checkImpValue(String value,Boolean checkFlag,ExcelSchemePropertyVo espVo,StringBuffer errorStr){
        if(!"".equals(StringUtil.formatEmpty(espVo.getFieldEmpty())) && !"null".equals(espVo.getFieldEmpty())){//如果该字段为非空
            if("true".equals(espVo.getFieldEmpty())) {
                //验证字段是否为空 //如果为空 设置为false
                if("".equals(value)){
                    errorStr.append(espVo.getPropertyTitle()+" 非空;");
                    checkFlag=false;
                }
            }
        }
        if(!"".equals(value)){
            //获得长度设置
            if(!"".equals(StringUtil.formatEmpty(espVo.getFieldLen())) && !"null".equals(espVo.getFieldLen())){
                Integer len=Integer.valueOf(espVo.getFieldLen());
                if(value.length()>len){
                    errorStr.append(espVo.getPropertyTitle()+" 超过长度限制"+len+";");
                    checkFlag=false;
                }
            }
            if(!"".equals(StringUtil.formatEmpty(espVo.getFieldType())) && !"null".equals(espVo.getFieldType())){
                //判断格式
                switch (espVo.getFieldType()){
                    case "number":
                        //判断是数字或浮点型
                        if(!NumberUtils.isNumber(value)){
                            //判断是否为float
                            try {
                                Float fValue=Float.valueOf(value);//判断能否转换为float 如果转换异常 则说明错误
                            }catch (Exception e){
                                errorStr.append(espVo.getPropertyTitle()+" 不是数字;");
                                checkFlag=false;
                            }
                        }
                        break;
                    case "date":
                        //判断是否为数字 说明是Long型 判断能否转为数字
                        if(NumberUtils.isNumber(value)){
                            try {
                                DateUtils.addDayLongTime(Long.valueOf(value),+1);
                            } catch (Exception e) {
                                errorStr.append(espVo.getPropertyTitle()+" 应该为时间格式;");
                                checkFlag=false;
                            }
                        }else{
                            try {
                                DateUtils.parseTime(value,"yyyy-MM-dd");
                            } catch (Exception e) {
                                errorStr.append(espVo.getPropertyTitle()+" 应该为时间格式;");
                                checkFlag=false;
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        return checkFlag;
    }

//
//    public static Map<String, ? extends BaseEntity> listToMap(List<? extends BaseEntity> entityList) {
//        if (null == entityList)
//            return null;
//
//        Map<String, BaseEntity> map = new HashMap<String, BaseEntity>();
//        for (int i = 0; i < entityList.size(); i++) {
//            map.put(entityList.get(i).getId(), entityList.get(i));
//        }
//
//        return map;
//    }


    public static BaseEntity rowToEntity(Row row, final ExcelSchemeVo schemeVo, String uid, String companyId) throws Exception {
        //有效性判断
        if (null == schemeVo || null == schemeVo.getProperyList() || schemeVo.getProperyList().size() == 0) {
            throw new Exception("无效的行或导入方案");
        }
        if (null == schemeVo.getClsQualifiedName() || StringUtils.isEmpty(schemeVo.getClsQualifiedName())) {
            throw new Exception("无效的导入实体，请检查导入方案！");
        }

        if (null == row || row.getLastCellNum() <= 0) {
            return null;
        }

        //遍历数据
        int colSize = Integer.valueOf(row.getLastCellNum());
        // 关键列信息
        int keyColNum = schemeVo.getKeyColumn() - 1;
        //关键列序号 大于Execl 行大小
        if (keyColNum > colSize - 1) {
            return null;
        }
        Cell cell;
        //Object value = new Object();
        //value
        //关键数据列暂停判断
//        cell = row.getCell(keyColNum);
//        if (null == cell) {
//            return null;
//        }
//        Object value = getCellValue(cell);
//        String valueStr = String.valueOf(value);
//        if ("null".equals(valueStr.toLowerCase()) || valueStr.length() == 0) {
//            return null;
//        }

        Class cls;
        try {
            cls = Class.forName(schemeVo.getClsQualifiedName());
            if (null == cls) {
                throw new Exception("无效的导入实体，请联系管理员重设导入实体！");
            }
        } catch (Exception e) {
            throw new Exception("无效的导入实体，请联系管理员重设导入实体！");
        }

        BaseEntity be = null;
        be = (BaseEntity) cls.newInstance();
        Field f = null;
        String typeName = null;
        Object cellValue = null;
        //属性列表
        List<ExcelSchemePropertyVo> propsList = schemeVo.getProperyList();
        //遍历属性
        int colNum = 0;

        for (ExcelSchemePropertyVo vo : propsList) {
            colNum = vo.getColumnNum() - 1;
            if (colNum < 0 || colNum >= colSize) {
                //小于行号，或大于行列数的字段不进行操作
                continue;
            }
            //导入方案模板以1开始
            cell = row.getCell(colNum);
            if (null == cell) {
                continue;
            }
            f = cls.getDeclaredField(vo.getPropertyName());
            if (null == f) {
                throw new Exception("无效的导入属性，请联系管理员重设导入实体！");
            }
            f.setAccessible(true);
            typeName = f.getType().getTypeName();
            cellValue = getCellValue(cell);
            String temp = "";
            if (typeName.endsWith("String")) {
                f.set(be, String.valueOf(cellValue));
            } else if (typeName.endsWith("Integer") || typeName.endsWith("int")) {
                temp = String.valueOf(cellValue).trim();
                if (temp.length() > 0) {
                    f.set(be, Integer.valueOf(temp));
                }

            } else if (typeName.endsWith("BigDecimal")) {
                temp = String.valueOf(cellValue).trim();
                if (temp.length() > 0) {
                    f.set(be, new BigDecimal(temp));
                }

            } else if (typeName.endsWith("Double") || typeName.endsWith("double")) {
                temp = String.valueOf(cellValue).trim();
                if (temp.length() > 0) {
                    f.set(be, Double.valueOf(temp));
                }

            } else if (typeName.endsWith("Float") || typeName.endsWith("float")) {
                temp = String.valueOf(cellValue).trim();
                if (temp.length() > 0) {
                    f.set(be, Float.valueOf(temp));
                }

            } else if (typeName.endsWith("Long") || typeName.endsWith("long")) {
                temp = String.valueOf(cellValue).trim();
                if (temp.length() > 0) {
                    f.set(be, Long.valueOf(temp));
                }

            } else if (typeName.endsWith("Date") && !StringUtils.isEmpty(cellValue)) {
                //另行处理
                f.set(be, ConcurrentDateFormatUtil.parse(String.valueOf(cellValue)).getTime());
            }

        }

        ///设置基本信息：创建人，创建时间等
        be.setCreateTime(System.currentTimeMillis());
        be.setCreateUser(uid);
        be.setUpdateTime(System.currentTimeMillis());
        be.setUpdateUser(uid);
        //设置导入公司
        f = cls.getDeclaredField("companyId");
        if (null != f) {
            f.setAccessible(true);
            f.set(be, companyId);
        }

        return be;
    }

    private static Object getCellValue(Cell cell) {
        int cellType = cell.getCellType();
        Object cellValue;
        switch (cellType) {
            case Cell.CELL_TYPE_BLANK:
                cellValue = "";
                break;
            case Cell.CELL_TYPE_BOOLEAN:
                cellValue = cell.getBooleanCellValue();
                break;
            case Cell.CELL_TYPE_NUMERIC:
                //cellValue = cell.getNumericCellValue();
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    double value = cell.getNumericCellValue();
                    Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);
                    cellValue = date.getTime();
                } else {
                    Double d = cell.getNumericCellValue();

                    cellValue = NUM_FORMATE.format(d);

                    // cellValue = cell.getNumericCellValue();
                }

                break;
            case Cell.CELL_TYPE_STRING:
                cellValue = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_FORMULA:
                cellValue = cell.getCellFormula();
                break;
            default:
                cellValue = cell.getStringCellValue();
                break;
        }
        return cellValue;
    }
}
